using System;
using System.Text.RegularExpressions;
using SecuBat.Logging;
using Css.Diagnostics;

namespace SecuBat.Crawling
{
	/// <summary>
	/// Summary description for WebAddress.
	/// </summary>
	public class WebAddress
	{
		private Uri _uri;
		private WebAddress _referer;
		private const String _schemeExpression = "^(\\w+?):";
		private Regex _schemeRegex;
		private String[] _allowedSchemes = {"http", "https"};
		
		public WebAddress(String url) : this(url, null)
		{
		}

		public WebAddress(String url, WebAddress referer)
		{
            _referer = referer;
			_schemeRegex = new Regex(_schemeExpression, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline);

			// Repair wrong "//domain.org/path/page.htm" links
			if (url.StartsWith("//"))
				url = "http:" + url;

			// Analyze url for scheme
			bool validSchemeFound = false;
			Match m = _schemeRegex.Match(url);
			if (m != null)
			{
				if (m.Value.Length > 0)
				{
					String scheme = m.Groups[1].Value;
					if (Uri.CheckSchemeName(scheme))
					{
						if (Array.IndexOf(_allowedSchemes, scheme.ToLower()) < 0)
							throw new InvalidWebAddressException("Scheme \"" + scheme + "\" in url \"" + url + "\" not supported, ignoring this address.");
						else
							validSchemeFound = true;
					}
					else
					{
						throw new InvalidWebAddressException("Scheme \"" + scheme + "\" in url \"" + url + "\" not valid.");
					}
				}
			}

			try
			{
				if (referer != null)
				{
					if (!validSchemeFound)
					{
						if (url.StartsWith("/"))
						{
							String path = referer.Scheme + "://" + referer.HostName + url;
							_uri = new Uri(path);
						}
						else
						{
							String path = referer.Scheme + "://" + referer.HostName + referer.BasePath + url;
							_uri = new Uri(path);
						}
					}
					else
						_uri = new Uri(url);
				}
				else
					_uri = new Uri(url);
			}
			catch (Exception ex)
			{
				throw new InvalidWebAddressException("Uri could not be created successfully from url \"" + url + "\"!", ex);
			}
		}

		public Uri Uri
		{
			get
			{
				return _uri;
			}
		}

		public String Url
		{
			get
			{
				return _uri.AbsoluteUri;
			}
		}
		public String HostName
		{
			get
			{
				return _uri.Host;
			}
		}

//		public String MainDomain
//		{
//			get
//			{
//				_uri.
//			}
//		}

		public String BasePath
		{
			get
			{
				int i = _uri.AbsolutePath.LastIndexOf("/");
				if (i > -1)
				{
					return _uri.AbsolutePath.Substring(0, i + 1);
				}
				return "/";
			}
		}

		public String QueryString
		{
			get {return _uri.Query;}
		}

		public String Scheme
		{
			get
			{
				return _uri.Scheme;
			}
		}

		public WebAddress Referer
		{
			get
			{
				return _referer;
			}
			set
			{
				_referer = value;
			}
		}
	}
}
